package br.unifor.cct.mia.evaluate;

import java.io.IOException;
import java.util.Map;
import java.util.StringTokenizer;

import weka.clusterers.ClusterEvaluation;
import weka.clusterers.Cobweb;
import weka.gui.explorer.ClustererPanel;
import br.unifor.cct.mia.dataenhancement.DatabaseUtil;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;
import br.unifor.cct.mia.util.SaveReport;

public class WekaIOCobwebEvaluate implements Evaluate {

	private Map genesAnt;
	private String structure;
	private String dataset;
	private ClustererPanel panel;
	private String[] options;
	
	private int clusterX = 2;
	private int splitX = 10;
	private int mergeX = 7;
	
	public double cost(Genotype gen) {		
		double sum = 0;
		
		Integer hashCode = new Integer(Methods.geneToString(gen.getGene()).hashCode());
		if (!genesAnt.containsKey(hashCode)) {			

			try {
				SaveReport report = new SaveReport("temp/result.txt",structure);
				
				for ( int i=0; i<gen.getGene().length; i++ ) {
					double value = gen.getGene(i);
					String line = DatabaseUtil.readLine(dataset,(int)value);						
					report.addLine(line);						
					
				}
				report.saveToDisk();
				
				String[] param = new String[2];
				param[0] = "-t";
				param[1] = "temp/result.txt";
				
				Cobweb cobweb = new Cobweb();
				String evaluate = ClusterEvaluation.evaluateClusterer(cobweb,param);
								
				StringTokenizer tokenizer = new StringTokenizer(evaluate,"\n");
				
				int mergers = 0;
				int splits = 0;
				int clusters = 0;
				int count = 0;
				while ( tokenizer.hasMoreTokens() ) {
					String token = tokenizer.nextToken();
					if ( count == 3 ) break;
					if ( token.startsWith("Number of merges:") ) {
						String aux = token.substring( 
								token.indexOf(":")+2, token.length() );
						mergers = Integer.parseInt(aux);
						count++;
					}
					else if ( token.startsWith("Number of splits:") ) {
						String aux = token.substring( 
								token.indexOf(":")+2, token.length() );
						splits = Integer.parseInt(aux);
						count++;
					}
					else if ( token.startsWith("Number of clusters:") ) {
						String aux = token.substring( 
								token.indexOf(":")+2, token.length() );
						clusters = Integer.parseInt(aux);
						count++;
					}
				}
								
				/*System.out.println("Cluster Finalizado");
				System.out.println("Splits: "+splits);
				System.out.println("Mergers: "+mergers);				
				System.out.println("Clusters: "+clusters);*/
				
				sum = (clusterX*clusters) + (mergeX*mergers) + (splitX*splits);
				
			} catch (IOException e1) {
				e1.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}			
			
			genesAnt.put(hashCode, new Double(sum));
		}
		else {
			sum = ((Double)genesAnt.get(hashCode)).doubleValue();
		}
		
		return sum;
	}

	public Object evaluate(Object value,String[] options) {
		this.options = options;		
		Object[] o = (Object[]) value;
		structure = (String) o[0];
		genesAnt = (Map) o[1];
		dataset = (String) o[2];
		panel = (ClustererPanel) o[3];	
		Ga Ga = (Ga)o[4];
		
		Ga.sum = 0;
		Ga.indexBestWorst[0] = Ga.indexBestWorst[1] = 0;
       
        for(int i = 0; i < Ga.configurations.getPopsize(); i++) {        	
        	Ga.population[i].setFitness(cost((Genotype)Ga.population[i]));                    	
            if (Ga.population[i].getFitness() < Ga.population[Ga.indexBestWorst[0]].getFitness()) 
            	Ga.indexBestWorst[0] = i;
            else 
            	if (Ga.population[i].getFitness() > Ga.population[Ga.indexBestWorst[1]].getFitness()) 
            		Ga.indexBestWorst[1] = i;
            	
            Ga.sum += Ga.population[i].getFitness();
        }
        
		return Ga.population;
	}
}
